#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstring>
#include <netinet/in.h>
#include<pthread.h>
using namespace std;
// dgram
struct ThreadData{

    struct sockaddr_in server;
    int socketfd;
};
//改成多线程
void Usage(std::string proc)
{
    std::cout << "\n\tUsage: " << proc << "serverip serverport" << endl;
}
void* Rec(void* args)
{
    auto it = static_cast<ThreadData*>(args);
    string mes;
    socklen_t len = sizeof(it->server);
    while(true)
    {
        cout << "Please Enter@";
        getline(cin, mes);
        sendto(it->socketfd, mes.c_str(), mes.size(), 0, (sockaddr *)&it->server, len);
    }
}

void* Send(void* args)
{
    auto it = static_cast<ThreadData*>(args);
    char buff[1024];
    while(true)
    {
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t s = recvfrom(it->socketfd,buff,1023,0,(sockaddr*)&temp,&len);

        if(s > 0)
        {
            buff[s] = 0;
            cout << "Client recv a message" << buff << endl;    
        }
    }
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(0);
    }
    std::string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    struct ThreadData td;
    int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
    td.socketfd = socketfd;
    if (socketfd < 0)
    {
        cout << "error " << endl;
        return 1;
    }
    // client 需要bind吗 ? ? ? 也需要! ! !
    // 只不过不需要用户显示的bind /一般由OS自由随机选择
    // 一个端口号只能由一个进程bind,对server是如此,对client也是!!!
    // 其实client的port是多少不重要,保证主机上的唯一性就可以.
    // 系统什么时候bind呢? ? ? 首次发送数据的时候
    string mes;
    struct sockaddr_in server;
    bzero(&td.server, sizeof(td.server));
    td.server.sin_family = AF_INET;
    td.server.sin_addr.s_addr = inet_addr(serverip.c_str());
    td.server.sin_port = htons(serverport);
    socklen_t len = sizeof(td.server);

    pthread_t rec,send;
    pthread_create(&rec,nullptr,Rec,(void*)&td);
    pthread_create(&send,nullptr,Send,(void*)&td);

    pthread_join(rec,nullptr);
    pthread_join(send,nullptr);
    close(socketfd);
    return 0;
}